package safeCommitter.test.finder.simple;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;

import safeCommitter.model.adpters.ClassEntity;
import safeCommitter.model.adpters.SCSingleMethodTest;
import safeCommitter.test.finder.core.ASCJavaFinder;
import safeCommitter.test.finder.core.ISCJavaFinder;

public class SCJavaSimpleFinder extends ASCJavaFinder implements ISCJavaFinder {

	public SCJavaSimpleFinder(final IJavaProject javaProject) {
		super(javaProject, new SCMethodRepository());
	}

	public Collection<? extends SCSingleMethodTest> findTestsFromMethods(
			final Set<ClassEntity> clazzEntities, final IProgressMonitor monitor)
			throws CoreException {
		monitor.beginTask("Fetching Tests", 40);
		monitor.subTask("Fetching Methods To check");
		SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 5);
		subMonitor.beginTask("Fetching Methods To check", clazzEntities.size());
		Set<IMethod> methodsToCheck = new HashSet<IMethod>();
		for (ClassEntity entity : clazzEntities) {
			methodsToCheck.addAll(entity.getMethods());
			subMonitor.worked(1);
		}
		subMonitor.done();
		if (monitor.isCanceled()) {
			return Collections.emptySet();
		}
		subMonitor = new SubProgressMonitor(monitor, 35);
		setRequestor(new SCSimpleSearchRequestor(repository));
		monitor.subTask("Starting recursive search");
		subMonitor.beginTask("Starting recursive search", 3 * methodsToCheck
				.size());
		if (methodsToCheck.size() > 0) {
			Set<SCSingleMethodTest> search = recursiveSearch(methodsToCheck, subMonitor);
			subMonitor.done();
			if (monitor.isCanceled()) {
				setUserCancelled(true);
				return Collections.emptySet();
			}
			return search;
		} else {
			return Collections.emptySet();
		}
	}

	private Set<SCSingleMethodTest> recursiveSearch(final Set<IMethod> methodsToCheck,
			final SubProgressMonitor subMonitor) {
		if (subMonitor.isCanceled()) {
			setUserCancelled(true);
			return Collections.emptySet();
		}
		for (IMethod m : methodsToCheck) {
			performJavaSearch(m, true);
			subMonitor.worked(1);
		}
		repository.removeMethodsFromMap(methodsToCheck);
		repository.addSearchedMethods(methodsToCheck);
		if (repository.getMethodsToCheck().size() > 0) {
			recursiveSearch(
					new HashSet<IMethod>(repository.getMethodsToCheck()),
					subMonitor);
		}
		subMonitor.done();
		return repository.getTestCalledSet();
	}

}
